package org.bing.engine.utility.helper;

import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.security.SecureRandom;
import java.util.Enumeration;

public class UuidGenerator {
	private static final SecureRandom random = new SecureRandom();
	private static final String IP = getLocalIpAddress();
	private static short counter = (short) 0;

	private static final String sep = "-";

	private static String getLocalIpAddress() {
		InetAddress addr = getLocalAddress();
		byte[] bs = addr == null ? new byte[] { 0, 0, 0, 0 } : addr.getAddress();
		return superFormat(toInt(bs), 10);
	}

	// from hibernate uuid generator
	private static long toInt(byte[] bytes) {
		long result = 0;
		for (int i = 0; i < 4; i++) {
			result = (result << 8) - Byte.MIN_VALUE + (int) bytes[i];
		}
		return result;
	}

	private static InetAddress getLocalAddress() {
		Enumeration<NetworkInterface> allNetInterfaces = null;
		try {
			allNetInterfaces = NetworkInterface.getNetworkInterfaces();
		} catch (SocketException e) {
			// ignore
		}
		while (allNetInterfaces != null && allNetInterfaces.hasMoreElements()) {
			NetworkInterface netInterface = (NetworkInterface) allNetInterfaces.nextElement();
			Enumeration<InetAddress> addresses = netInterface.getInetAddresses();
			while (addresses.hasMoreElements()) {
				InetAddress addr = (InetAddress) addresses.nextElement();
				if (addr != null && addr instanceof Inet4Address) {
					String ip = addr.getHostAddress();
					if (!ip.startsWith("127.")) {
						return addr;
					}
				}
			}
		}
		return null;
	}

	protected static String superFormat(long val, int len) {
		String src = Long.toString(val, 32);
		String s = new String("0000000000");
		s = s + src;
		return s.substring(s.length() - len);
	}

	protected short getCount() {
		synchronized (UuidGenerator.class) {
			if (counter < 0)
				counter = 0;
			return counter++;
		}
	}

	// 30
	public String generate() {
		StringBuffer sb = new StringBuffer(30);
		// 10 bytes
		sb.append(IP);
		sb.append(sep);
		// 10 bytes
		sb.append(superFormat(System.currentTimeMillis(), 10));
		sb.append(sep);
		// 4 bytes
		sb.append(superFormat(getCount(), 4));
		// 4 bytes
		sb.append(superFormat(random.nextInt(10000), 4));
		return sb.toString();
	}

	public static void main(String[] args) throws Exception {
		UuidGenerator gen = new UuidGenerator();
		System.out.println("----------------------------------------");
		long t1 = System.currentTimeMillis();
		for (int i = 0; i < 10 * 10000; i++) {
			String id = (String) gen.generate();
			System.out.println(id);
		}
		long t2 = System.currentTimeMillis();
		System.out.println("----------------------------------------");
		System.out.println(t2 - t1);
	}
}
